package net.gagnat.android.trackit.provider;

import java.util.HashMap;

import net.gagnat.android.trackit.db.DatabaseHelper;
import net.gagnat.android.trackit.util.TrackItConstants;
import net.gagnat.android.trackit.util.TrackItConstants.LogEntryColumns;
import net.gagnat.android.trackit.util.TrackItConstants.LogTagColumns;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class LogItProvider extends ContentProvider {

	static final String DATABASE_NAME = "log_it.db";
	static final String LOG_ENTRY_TABLE_NAME = "logentry";
	static final String LOG_TAG_TABLE_NAME = "logtag";
	static final String LOG_ENTRY_TAG_LINK_TABLE_NAME = "logentrytaglink";
	static final int DATABASE_VERSION = 1;
	private static final int LOG_ENTRIES = 1;
	private static final int LOG_ENTRY_ID = 2;
	private static final int LOG_TAGS = 3;
	private static final int LOG_TAG_ID = 4;
	private static final int TAGS_FOR_ENTRY = 5;

	private static UriMatcher sUriMatcher;
	private static HashMap<String, String> sLogEntriesProjectionMap;
	private static HashMap<String, String> sLogTagsProjectionMap;

	private SQLiteOpenHelper mOpenHelper;

	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
//		SQLiteDatabase database = mOpenHelper.getWritableDatabase();
//		ContentValues values = new ContentValues();
//		values.put(LogTag.NAME, "study");
//		database.insert(LOG_TAG_TABLE_NAME, LogTag.NAME, values);
//		values = new ContentValues();
//		values.put(LogTag.NAME, "training");
//		database.insert(LOG_TAG_TABLE_NAME, LogTag.NAME, values);
//		values = new ContentValues();
//		values.put(LogTag.NAME, "housework");
//		database.insert(LOG_TAG_TABLE_NAME, LogTag.NAME, values);
//		values = new ContentValues();
//		values.put(LogTag.NAME, "work");
//		database.insert(LOG_TAG_TABLE_NAME, LogTag.NAME, values);
//		database.execSQL("insert into " + LOG_TAG_TABLE_NAME + " values('study');");
//		database.execSQL("insert into " + LOG_TAG_TABLE_NAME + " values('training');");
//		database.execSQL("insert into " + LOG_TAG_TABLE_NAME + " values('housework');");
//		database.execSQL("insert into " + LOG_TAG_TABLE_NAME + " values('work');");
		return true;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case LOG_ENTRIES:
			count = db.delete(LOG_ENTRY_TABLE_NAME, selection, selectionArgs);
			break;
		case LOG_ENTRY_ID:
			String logEntryId = uri.getPathSegments().get(1);
			count = db.delete(LOG_ENTRY_TABLE_NAME, LogEntryColumns._ID + "=" + logEntryId
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case LOG_ENTRIES:
			return LogEntryColumns.CONTENT_TYPE;
		case LOG_ENTRY_ID:
			return LogEntryColumns.CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		if (sUriMatcher.match(uri) != LOG_ENTRIES) {
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		ContentValues values = null;
		if (initialValues != null) {
			values = new ContentValues(initialValues);
		} else {
			values = new ContentValues();
		}

		if (values.containsKey(LogEntryColumns.CREATED_DATE) == false) {
			values.put(LogEntryColumns.CREATED_DATE, System.currentTimeMillis());
		}

		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowId = db.insert(LOG_ENTRY_TABLE_NAME, LogEntryColumns.TITLE, values);
		if (rowId > 0) {
			Uri logEntryUri = ContentUris.withAppendedId(LogEntryColumns.CONTENT_URI, rowId);
			getContext().getContentResolver().notifyChange(logEntryUri, null);
			return logEntryUri;
		}

		throw new SQLException("Failed to insert row into " + uri);
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

		switch (sUriMatcher.match(uri)) {
		case LOG_ENTRIES:
			qb.setTables(LOG_ENTRY_TABLE_NAME);
			qb.setProjectionMap(sLogEntriesProjectionMap);
			break;
		case LOG_ENTRY_ID:
			qb.setTables(LOG_ENTRY_TABLE_NAME);
			qb.setProjectionMap(sLogEntriesProjectionMap);
			qb.appendWhere(LogEntryColumns._ID + "=" + uri.getPathSegments().get(1));
			break;
		case LOG_TAGS:
			qb.setTables(LOG_TAG_TABLE_NAME);
			qb.setProjectionMap(sLogTagsProjectionMap);
			break;
		case TAGS_FOR_ENTRY:
			qb.setTables(LOG_ENTRY_TAG_LINK_TABLE_NAME + " link JOIN " + LOG_TAG_TABLE_NAME + " tag on (link.log_tag_id = tag._id)");
			qb.setProjectionMap(sLogTagsProjectionMap);
			qb.appendWhere("link.log_entry_id=" + uri.getPathSegments().get(1));
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		String orderBy;
		if (TextUtils.isEmpty(sortOrder)) {
			orderBy = null;
		} else {
			orderBy = sortOrder;
		}

		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);

		// Tell the cursor what uri to watch, so it knows when its source data
		// changes
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case LOG_ENTRIES:
			count = db.update(LOG_ENTRY_TABLE_NAME, values, where, whereArgs);
			break;
		case LOG_ENTRY_ID:
			String logEntryId = uri.getPathSegments().get(1);
			count = db.update(LOG_ENTRY_TABLE_NAME, values, LogEntryColumns._ID + "=" + logEntryId
					+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(TrackItConstants.AUTHORITY, "logentries", LOG_ENTRIES);
		sUriMatcher.addURI(TrackItConstants.AUTHORITY, "logentries/#", LOG_ENTRY_ID);
		sUriMatcher.addURI(TrackItConstants.AUTHORITY, "logtags", LOG_TAGS);
		sUriMatcher.addURI(TrackItConstants.AUTHORITY, "logtags/#", LOG_TAG_ID);
		sUriMatcher.addURI(TrackItConstants.AUTHORITY, "tags/logentry/#", TAGS_FOR_ENTRY);

		sLogEntriesProjectionMap = new HashMap<String, String>();
		sLogEntriesProjectionMap.put(LogEntryColumns._ID, LogEntryColumns._ID);
		sLogEntriesProjectionMap.put(LogEntryColumns.TITLE, LogEntryColumns.TITLE);
		sLogEntriesProjectionMap.put(LogEntryColumns.CREATED_DATE, LogEntryColumns.CREATED_DATE);

		sLogTagsProjectionMap = new HashMap<String, String>();
		sLogTagsProjectionMap.put(LogTagColumns._ID, LogTagColumns._ID);
		sLogTagsProjectionMap.put(LogTagColumns.NAME, LogTagColumns.NAME);
	}

}
